import XmlDom from './xmlDom'
import XMLNodeTypes from './xmlNodeTypes'

/**
 * 转换xml字符串到Codemirror支持的Tags格式
 */
const xml2Tags = (xml, tags) => {
  const xmlDom = XmlDom.createXmlDom(xml)
  xmlDom2Tags(xmlDom, tags)
}

/**
 * 转换xmlDom到Tags格式
 */
const xmlDom2Tags = (xmlDom, tags) => {
  if (xmlDom !== null && xmlDom !== undefined) {
    const rootNode = xmlDom.documentElement
    if (rootNode) {
      // 如果tags['!top']中没这个顶级节点，那么插入到tags['!top']中
      if (tags['!top'].indexOf(rootNode.tagName) === -1) {
        tags['!top'].push(rootNode.tagName)
      }

      xmlNode2Tags(rootNode, tags)
    }
  }
}
/**
 * 转换xmlDom的一个节点到Tags格式
 */
const xmlNode2Tags = (node, tags) => {
  // 只处理正常的元素节点，不处理文本节点和注释节点
  if (node.nodeType === XMLNodeTypes.ELEMENT_NODE) {
    buildTagsEle(node, tags)
  }
}

// 根据node节点构建tags下的元素
const buildTagsEle = (eleNode, tags) => {
  const eleName = eleNode.tagName
  // tags下是否已存在同名元素
  const isExistEle = !!(tags[eleName])
  // 不存在同名元素则,在tags下增加一个元素
  if (!isExistEle) {
    tags[eleName] = {}
  }
  // 构建tags下元素的attrs
  buildEleAttrs(eleNode, tags)
  // 构建tags下元素的children
  buildChildren(eleNode, tags)
}

// 根据节点构建tags下的元素属性
const buildEleAttrs = (eleNode, tags) => {
  const eleName = eleNode.tagName
  const attrs = XmlDom.getElementAttributes(eleNode)
  // tags下该元素如果不存在属性集合，且元素有属性,则新建一个attrs
  if (!tags[eleName].attrs && attrs && attrs.length > 0) {
    tags[eleName].attrs = {}
  }
  // 遍历元素下属性集合，生成tags下的属性集合
  for (let i = 0, len = attrs.length; i < len; i++) {
    const attrName = attrs[i].name
    const attrValue = attrs[i].value

    // 如果之前已存在该属性，则插入到属性中
    if (tags[eleName].attrs[attrName]) {
      // 如果属性原来的值数组中不存在该值，则插入到该值数组
      if (tags[eleName].attrs[attrName].indexOf(attrValue) === -1) {
        tags[eleName].attrs[attrName].push(attrValue)
      }
    } else {
      // 如果之前不存在该属性，则初始化
      tags[eleName].attrs[attrName] = [attrValue]
    }
  }
}

// 根据节点构建tags下的元素的子节点属性
const buildChildren = (eleNode, tags) => {
  const childNodes = XmlDom.getElementChildren(eleNode)
  const eleName = eleNode.tagName
  if (childNodes && childNodes.length > 0) {
    // 子元素名数组
    const childNames = childNodes.map(l => l.tagName)
    // 如果之前已存在children，则数组
    if (tags[eleName].children) {
      const oldValues = tags[eleName].children
      tags[eleName].children = [...new Set([...oldValues, ...childNames])]
    } else {
      // 如果之前不存在children，则数组
      tags[eleName].children = childNames
    }
    // 递归构建子元素
    for (let i = 0, len = childNodes.length; i < len; i++) {
      buildTagsEle(childNodes[i], tags)
    }
  }
}

export default xml2Tags
